/*
*********************************
	  SF2D Engine
*********************************

	By Julian Williams
	September 28, 2010
**********************************

	Description:

		Script registered class to use 
	2D Mathmatical vectors within 
	the application. Uses box2d's
	b2Vec2, because its much more 
	complete than SFML's currently
***********************************
*/
#include <Box2D\Box2D.h>
#include <assert.h>

#include "script_engine.h"
#include "script_vector2.h"





//Wrap some Math functions upz
float DotProduct(const b2Vec2 &v1, const b2Vec2 &v2)
{
	return static_cast<float>(b2Dot(v1, v2));
}//EoF

float CrossProduct(const b2Vec2 &v1, const b2Vec2 &v2)
{
	return b2Cross(v1, v2);
}//EoF

//-----------------------
// AngelScript functions
//-----------------------

static void Vector2DefaultConstructor(b2Vec2 *self)
{
	new(self) b2Vec2();
}

static void Vector2CopyConstructor(const b2Vec2 &other, b2Vec2 *self)
{
	new(self) b2Vec2(other);
}

static void Vector2InitConstructor(float x, float y, b2Vec2 *self)
{
	new(self) b2Vec2(x, y);
}



int RegisterScriptVector2( asIScriptEngine *engine )
{

	int r;

	// Register the type
	r = engine->RegisterObjectType("vector2", sizeof(b2Vec2), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_CA); assert( r >= 0 );

	// Register the object properties
	r = engine->RegisterObjectProperty("vector2", "float x", offsetof(b2Vec2, x)); assert( r >= 0 );
	r = engine->RegisterObjectProperty("vector2", "float y", offsetof(b2Vec2, y)); assert( r >= 0 );

	// Register the constructors
	r = engine->RegisterObjectBehaviour("vector2", asBEHAVE_CONSTRUCT,  "void f()",                     asFUNCTION(Vector2DefaultConstructor), asCALL_CDECL_OBJLAST); assert( r >= 0 );
	r = engine->RegisterObjectBehaviour("vector2", asBEHAVE_CONSTRUCT,  "void f(const vector2 &in)",    asFUNCTION(Vector2CopyConstructor), asCALL_CDECL_OBJLAST); assert( r >= 0 );
	r = engine->RegisterObjectBehaviour("vector2", asBEHAVE_CONSTRUCT,  "void f(float, float)",			asFUNCTION(Vector2InitConstructor), asCALL_CDECL_OBJLAST); assert( r >= 0 );


	// Register the operator overloads
	r = engine->RegisterObjectMethod("vector2", "vector2 &opAddAssign(const vector2 &in)", asMETHODPR(b2Vec2, operator+=, (const b2Vec2 &), void), asCALL_THISCALL); assert( r >= 0 );
	r = engine->RegisterObjectMethod("vector2", "vector2 &opSubAssign(const vector2 &in)", asMETHODPR(b2Vec2, operator-=, (const b2Vec2 &), void), asCALL_THISCALL); assert( r >= 0 );
	r = engine->RegisterObjectMethod("vector2", "bool opEquals(const vector2 &in) const", asFUNCTIONPR(operator==, (const b2Vec2&, const b2Vec2&), bool), asCALL_CDECL_OBJFIRST); assert( r >= 0 );
	r = engine->RegisterObjectMethod("vector2", "vector2 opAdd(const vector2 &in) const", asFUNCTIONPR(operator+, (const b2Vec2&, const b2Vec2&), b2Vec2), asCALL_CDECL_OBJFIRST); assert( r >= 0 );
	r = engine->RegisterObjectMethod("vector2", "vector2 opMul_r(float) const", asFUNCTIONPR(operator*, (float, const b2Vec2&), b2Vec2), asCALL_CDECL_OBJLAST); assert( r >= 0 );

	// Register the object methods
	r = engine->RegisterObjectMethod("vector2", "float Length() const", asMETHOD(b2Vec2, Length), asCALL_THISCALL); assert( r >= 0 );
	r = engine->RegisterObjectMethod("vector2", "float LengthSquared() const", asMETHOD(b2Vec2, LengthSquared), asCALL_THISCALL); assert( r >= 0 );
	r = engine->RegisterObjectMethod("vector2", "float Normalize() const", asMETHOD(b2Vec2, Normalize), asCALL_THISCALL); assert( r >= 0 );
	
	//Register related global functions
	r = engine->RegisterGlobalFunction("float DotProduct(const vector2 &in, const vector2 &in)", asFUNCTIONPR(b2Dot,(const b2Vec2 &, const b2Vec2 &), float), asCALL_CDECL); assert( r >= 0 );
	r = engine->RegisterGlobalFunction("float CrossProduct(const vector2 &in, const vector2 &in)", asFUNCTIONPR(b2Cross,(const b2Vec2 &, const b2Vec2 &), float), asCALL_CDECL); assert( r >= 0 );
	
	return r;
}//EoF